package com.micro.platform.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.micro.platform.starter.domain.PageFilter;
import com.micro.platform.starter.domain.PageResult;
import com.micro.platform.starter.utils.AssertUtil;
import com.micro.platform.starter.utils.BeanCopyUtil;
import com.micro.platform.user.controller.role.*;
import com.micro.platform.user.entity.*;
import com.micro.platform.user.mapper.RoleMapper;
import com.micro.platform.user.mapper.UserRoleMapper;
import com.micro.platform.user.service.FunctionService;
import com.micro.platform.user.service.RoleFunctionService;
import com.micro.platform.user.service.RoleService;
import com.micro.platform.user.service.UserRoleService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户-角色表 服务实现类
 * </p>
 *
 * @author zhouyk
 * @since 2021-12-06
 */
@Service
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements RoleService {
    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private FunctionService functionService;

    @Autowired
    private UserRoleService userRoleService;

    @Autowired
    private RoleFunctionService roleFunctionService;

    @Override
    public List<Role> getRolesByUserId(Long userId) {
        if(null == userId){
            return Collections.emptyList();
        }
        QueryWrapper<UserRole> queryWrapperUserRole = new QueryWrapper<>();
        queryWrapperUserRole.lambda().eq(UserRole::getUserId, userId);
        List<UserRole> userRoles = userRoleMapper.selectList(queryWrapperUserRole);
        List<Long> roleIds = userRoles.stream().map(UserRole::getRoleId).distinct().collect(Collectors.toList());
        return getRolesByIds(roleIds);
    }

    @Override
    public List<Role> getRolesByIds(List<Long> roleIds) {
        if(CollectionUtils.isEmpty(roleIds)){
            return Collections.EMPTY_LIST;
        }
        QueryWrapper<Role> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().in(Role::getId, roleIds);
        return roleMapper.selectList(queryWrapper);
    }

    @Override
    public Boolean addRole(RoleNewRequ roleNewRequ) {
        QueryWrapper<Role> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Role::getCode, roleNewRequ.getCode());
        List<Role> roles = roleMapper.selectList(queryWrapper);

        AssertUtil.isEmptyCollection(roles, "该角色代码已存在");

        Role role = BeanCopyUtil.copyProperties(roleNewRequ, Role::new);

        boolean save = save(role);
        List<Long> functionIds = roleNewRequ.getFunctionIds();
        if(CollectionUtils.isNotEmpty(functionIds)){
            Long id = role.getId();
            saveRoleFunction(functionIds, id);
        }
        return save;
    }

    @Override
    public PageResult<RoleInfosResp> pageFilter(PageFilter<RolePageFilterRequ> pageFilter) {
        RolePageFilterRequ filter = pageFilter.getFilter();
        QueryWrapper<Role> pageFilterQueryWrapper = null;
        if(null != filter){
            pageFilterQueryWrapper = new QueryWrapper<>();
            LambdaQueryWrapper<Role> lambda = pageFilterQueryWrapper.lambda();
            if(StringUtils.isNotEmpty(filter.getName())){
                lambda.likeRight(Role::getName, filter.getName());
            }
            if(null != filter.getType()){
                lambda.eq(Role::getType, filter.getType());
            }
        }
        Page<User> page = roleMapper.selectPage(pageFilter.toPage(), pageFilterQueryWrapper);
        PageResult<RoleInfosResp> pageResult = PageResult.build(page, RoleInfosResp::new);
        List<RoleInfosResp> records = pageResult.getRecords();
        List<Long> roleIds = records.stream().map(RoleInfosResp::getId).collect(Collectors.toList());
        List<RoleFunction> roleFunctions = roleFunctionService.getRoleFunctionsByRoleIds(roleIds);
        Map<Long, List<Long>> mapRoleId2FunctionIds = roleFunctions.stream().collect(Collectors.groupingBy(RoleFunction::getRoleId, Collectors.mapping(RoleFunction::getFunctionId, Collectors.toList())));
        for (RoleInfosResp record : records) {
            Long id = record.getId();
            List<Long> longs = mapRoleId2FunctionIds.get(id);
            if(null == longs){
                longs = Collections.EMPTY_LIST;
            }
            record.setFunctionIds(longs);
        }
        return pageResult;
    }

    @Override
    public List<RoleInfosResp> listAll() {
        QueryWrapper<Role> deptQueryWrapper = new QueryWrapper<>();
        deptQueryWrapper.lambda().eq(Role::getDeleted, Boolean.FALSE);
        List<Role> list = list(deptQueryWrapper);
        List<RoleInfosResp> listResps = BeanCopyUtil.copyListProperties(list, RoleInfosResp::new);
        if(listResps == null){
            return Collections.emptyList();
        }
        return listResps;
    }

    @Override
    public Boolean edited(RoleEditedRequ roleEditedRequ) {
        QueryWrapper<Role> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(Role::getCode, roleEditedRequ.getCode())
                .ne(Role::getId, roleEditedRequ.getId());
        List<Role> roles = roleMapper.selectList(queryWrapper);
        AssertUtil.isEmptyCollection(roles, "该角色代码已存在");

        Role role = BeanCopyUtil.copyProperties(roleEditedRequ, Role::new);

        boolean update = this.updateById(role);
        List<Long> functionIds = roleEditedRequ.getFunctionIds();
        if(CollectionUtils.isNotEmpty(functionIds)){
            Long id = role.getId();
            roleFunctionService.removeRoleFunctionByRoleId(id);
            saveRoleFunction(functionIds, id);
        }
        return update;
    }

    @Override
    public Boolean deleted(RoleDeletedRequ roleDeletedRequ) {
        Long id = roleDeletedRequ.getId();
        UserRole userRoleByRoleId = userRoleService.getUserRoleByRoleId(id);
        AssertUtil.isNull(userRoleByRoleId, "角色已绑定用户");
        boolean b = removeById(id);
        if(b){
            roleFunctionService.removeRoleFunctionByRoleId(id);
        }
        return b;
    }

    private void saveRoleFunction(List<Long> functionIds, Long id){
        if(CollectionUtils.isEmpty(functionIds) || id == null){
            return;
        }
        List<Function> functions = functionService.listByIds(functionIds);
        List<RoleFunction> roleFunctions = functions.stream().map(function -> {
            RoleFunction roleFunction = new RoleFunction();
            roleFunction.setFunctionId(function.getId());
            roleFunction.setRoleId(id);
            return roleFunction;
        }).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(roleFunctions)){
            roleFunctionService.saveBatch(roleFunctions);
        }
    }

    @Override
    public List<Role> getRolesByRoleCode(String roleCode) {
        if(StringUtils.isEmpty(roleCode)){
            return Collections.emptyList();
        }
        QueryWrapper<Role> deptQueryWrapper = new QueryWrapper<>();
        deptQueryWrapper.lambda()
                .eq(Role::getDeleted, Boolean.FALSE)
                .eq(Role::getCode, roleCode);
        return list(deptQueryWrapper);
    }
}
